package com.magima.core.repository;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

import android.annotation.TargetApi;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteException;
import android.database.sqlite.SQLiteOpenHelper;
import android.database.sqlite.SQLiteStatement;
import android.os.Build;

public class DataBaseRepository extends Repository {
	protected SQLiteOpenHelper mHelper;
	protected String mTable;
	private static final int DATABASE_VERSION = 1;
	
	protected static String DATA_FIELD = "data";
	protected static HashMap<String, Lock> mLockPool = new HashMap<String, Lock>();
	
	protected class MySQLiteHelper extends SQLiteOpenHelper {
		public static final String COLUMN_ID = "id";

		protected String mTable;

		public MySQLiteHelper(Context context, String database, String table, int version) {
			super(context, database, null, version);
			mTable = table;
		}

		@Override
		public void onCreate(SQLiteDatabase database) {
			database.execSQL("create table " + mTable + "(" + COLUMN_ID
					+ " text primary key, " + DATA_FIELD
					+ " text);");
		}

		@Override
		public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
			db.execSQL("DROP TABLE IF EXISTS " + mTable);
			onCreate(db);
		}

	}

	public DataBaseRepository(StringProcessor processor, Context context,
			String database, String table) {
		super(processor);
		table = table.replaceAll("-", "_");
		mHelper = newSQLiteHelper(context, database, table);
		mTable = table;
		mName = table;
		initLock(database);
		init();
	}
	
	private void initLock(String database){
		mLock = mLockPool.get(database);
		if ( mLock == null ) {
			mLock = new ReentrantLock(true);
			mLockPool.put(database, mLock);
		}
	}

	public DataBaseRepository(Context context, String database, String table) {
		this(null, context, database, table);
	}
	
	protected SQLiteOpenHelper newSQLiteHelper(Context context, String database, String table){
		return new MySQLiteHelper(context, database, table, DATABASE_VERSION);
	}
	
	public String getTable(){
		return mTable;
	}
	
	protected void init(){
		mLock.lock();
		try {
			mHelper.getWritableDatabase().execSQL("create table " + mTable + "(" + MySQLiteHelper.COLUMN_ID
					+ " text primary key, " + DATA_FIELD
					+ " text);");
			RepositoryManager.getInstance().setRepositoryVersionLatest(this);
		} catch (SQLiteException e){
			//if table exist, exception will happen, set latest version wont execute
		} finally {
			mHelper.close();
			mLock.unlock();
		}
	}
	
	@TargetApi(Build.VERSION_CODES.FROYO)
	@Override
	public void saveString(String id, String data) {
		ContentValues values = new ContentValues();
		values.put(DATA_FIELD, mProcessor.encodeString(data));
		values.put(MySQLiteHelper.COLUMN_ID, id);
		mHelper.getWritableDatabase().insertWithOnConflict(mTable, null, values, SQLiteDatabase.CONFLICT_REPLACE);
		mHelper.close();
	}
	
	public void saveStrings(String[] keys, String[] datas) {
		SQLiteDatabase db = mHelper.getWritableDatabase();
		try {
			db.beginTransaction();
			String sql = "Insert or Replace into "+mTable+" ("+MySQLiteHelper.COLUMN_ID+", "+DATA_FIELD+") values(?,?)";
            SQLiteStatement insert = db.compileStatement(sql);
            for(int i=0;i<keys.length;i++){
                
                insert.bindString(1, keys[i]);
                insert.bindString(2, datas[i]);
                insert.execute();
            }
            db.setTransactionSuccessful();
		} finally {
			db.endTransaction();
			mHelper.close();
		}		
	}
	
	@Override
	public String loadString(String id) {
		Cursor cursor = null;
		String str = null;
		if ( id.equals("last") ) {
			cursor = mHelper.getReadableDatabase().query(mTable,new String[]{DATA_FIELD}, null ,null, null, null, null);
			if ( cursor != null ) {
				if ( cursor.moveToLast() ) {
					str = mProcessor.decodeString(cursor.getString(cursor.getColumnIndex(DATA_FIELD)));
				}
			}
		} else if ( id.equals("first") ) {
			cursor = mHelper.getReadableDatabase().query(mTable,new String[]{DATA_FIELD}, null ,null, null, null, null);
			if ( cursor != null ) {
				if ( cursor.moveToFirst() ) {
					str = mProcessor.decodeString(cursor.getString(cursor.getColumnIndex(DATA_FIELD)));
				}
			}
		} else {			
			cursor = mHelper.getReadableDatabase().query(mTable,new String[]{DATA_FIELD}, "id=\""+id+"\"",null, null, null, null);
			if ( cursor != null ) {
				if ( cursor.moveToFirst() ) {
					str = mProcessor.decodeString(cursor.getString(cursor.getColumnIndex(DATA_FIELD)));
				}
			}
		}
		if ( cursor != null )
			cursor.close();
		mHelper.close();
		return str;
	}	
	
	@Override
	public List<String> loadAllString() {
		ArrayList<String> list = new ArrayList<String>();
		Cursor cursor = mHelper.getReadableDatabase().query(mTable,new String[]{DATA_FIELD}, null ,null, null, null, null);
		if ( cursor != null ){
			if ( cursor.moveToFirst() ) {
				do {
					list.add(mProcessor.decodeString(cursor.getString(cursor.getColumnIndex(DATA_FIELD))));
				} while ( cursor.moveToNext() );
			}
			cursor.close();
		}
		mHelper.close();
		return list;
	}
	
	@Override
	public void remove(String id){
		mHelper.getWritableDatabase().delete(mTable, "id=\""+id+"\"", null);
		mHelper.close();
	}
	
	@Override
	public void remove(){
		mHelper.getWritableDatabase().execSQL("DROP TABLE IF EXISTS " + mTable);		
		mHelper.close();
		init();
	}
}
